package typedefault

import (
	"codejy/analysis"
	"codejy/globalfunc"
	"codejy/linestrategy"
	"codejy/store"
	"codejy/structdef"
	"codejy/utils"
	"fmt"
	"reflect"
	"strings"
)

func init() {
	globalfunc.RegisterFuncAll("ExecuteTypeDefault", ExecuteTypeDefault)
	globalfunc.RegisterFuncAll("InjectTypeDefault", InjectTypeDefault)

}

var TypeDefaults = make(map[string]structdef.TypeDefault)

// 注册策略
func RegisterTypeDefault(f structdef.TypeDefault) {
	//判断是否已经存在
	if _, ok := TypeDefaults[f.GetTypeName()]; ok {
		panic("默认类型已经注册过了")
	}
	TypeDefaults[f.GetTypeName()] = f
}

// 通过类型名称获取类型
func GetTypeDefault(typeName string) structdef.TypeDefault {
	if f, ok := TypeDefaults[typeName]; ok {
		return f
	}
	return nil
}

func Execute(threadStore *structdef.ThreadStore, o structdef.TypeDefault, addr string, funName string, parameter ...string) string {
	var funcs reflect.Value
	if funName != "CreateTypeDefault" {
		data := store.GetTypeDefaultInstanceStore(threadStore, o.GetTypeName(), addr)
		if data != nil {
			funcs = reflect.ValueOf(data.(structdef.TypeDefault))
		} else {
			panic(fmt.Sprintf(o.GetTypeName()+"类型的实例不存在:%s", addr))
		}
	} else {
		funcs = reflect.ValueOf(o)
	}
	//根据每个类型自定义的参数解析方法,解析参数
	value := funcs.MethodByName("ParameterProcessing").Call([]reflect.Value{reflect.ValueOf(parameter)})
	parameter1 := value[0].Interface().([]string)
	if len(parameter1) != 0 { //如果参数是空,则不处理
		parameter = parameter1
	}
	var values []reflect.Value
	for i := range parameter {
		values = append(values, reflect.ValueOf(parameter[i]))
	}
	if funName == "CreateTypeDefault" {
		//addr，threadStore添加开头values
		values = append([]reflect.Value{reflect.ValueOf(addr), reflect.ValueOf(threadStore)}, values...)
	}

	call := funcs.MethodByName(funName).Call(values)

	if len(call) == 0 || call[0].Interface() == nil || call[0].Interface().(string) == "" {
		return `""`
	}
	v := call[0].Interface().(string)
	return analysis.AddDoubleQuotationMarks1(v)
}

// 执行策略
func ExecuteTypeDefault(threadStore *structdef.ThreadStore, addr string, typeName string, funName string, parameter []string) string {
	defer func() {
		if r := recover(); r != nil {
			panic(fmt.Sprintf("核心函数执行错误::::::类型名称:%s,函数名称:%s,参数:%s ,错误细节:%s", typeName, funName, parameter, r))
		}
	}()

	//判断是否有策略
	if _, ok := TypeDefaults[typeName]; !ok {
		panic("函数不存在")
	}
	execute := TypeDefaults[typeName]
	result := Execute(threadStore, execute, addr, funName, parameter...)
	return result
}

// 注入核心类型
func InjectTypeDefault(sealityFilePath string) {
	if !store.GetCoreFileLoaded() {
		//装载底层核心
		for _, v := range TypeDefaults {
			def := v.GetDef()
			//字符串按行分割
			resultList := strings.Split(def, "\n")
			codes := structdef.ToLineCode(resultList, sealityFilePath)
			//去除注释和空格,验证赋值变量名称是否合法
			codes = linestrategy.SkipCommentAndEmpty(codes)
			fileLineCode := structdef.AnalyseTypeOrFunLineCode(codes, sealityFilePath)
			//获取函数和类型定义,装载到内存中
			globalfunc.ExecuteFunc("DefanalysisMode", &fileLineCode, sealityFilePath)
		}
		store.SetCoreFileLoaded(true)
	}

}

// 获取核心文档定义和说明
func TypedefaultDoc(typeName string) {
	//判断是否有策略
	if _, ok := TypeDefaults[typeName]; !ok {
		panic("类型不存在,请检查类型名称是否正确")
	}
	def := TypeDefaults[typeName].GetDef()
	fmt.Println(def)
}

// 默认类型实例创建,并且返回实例地址
func TypeDefaultNewInstance(typeName string, threadStore *structdef.ThreadStore) string {
	addr := utils.InstantiateAddressGeneratoSafe() //生成实例地址
	store.NweStatusRestore(threadStore, func() string {
		handleFilePath := threadStore.HandleFilePath
		//注册实例
		properties := globalfunc.ExecuteFunc("InitProperties", threadStore, typeName, []structdef.PropertiesDefinition{}, []string{}, handleFilePath).(map[string]structdef.VarDefinition)
		store.RegisterInstance(threadStore, addr, properties)
		threadStore.CurrentInstanceAddress = addr
		//无须执行init方法,调用方会主动初始化
		////拿到类型定义
		//typeDefinition := store.GetTypeDefinition(handleFilePath, typeName)
		////执行初始化init方法,创建实例
		//definition, p := typeDefinition.Methods["init"]
		//if p {
		//	globalfunc.ExecuteFunc("ExecuteTypeMethod", threadStore, "init", definition, []string{}) //执行方法
		//}
		return ""
	})
	return addr
}

// 获取实际类型数据,泛型
func GetTypeDefaultValue[T any](threadStore *structdef.ThreadStore, typeName, instanceId string) (T, bool) {
	data := store.GetTypeDefaultInstanceStore(threadStore, typeName, instanceId)
	if data == nil {
		var t T
		return t, false
	}
	getData := data.(structdef.TypeDefault).GetData()
	if getData == nil {
		var t T
		return t, false

	}
	return getData.(T), true
}
